/**
 * Clase principal del programa.
 * 
 * @author HPCIII_Team2013
 */
package cl.ucn.hpc;

import cl.ucn.hpc.procesamiento.WordProcessing;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.LinkedBlockingQueue;

import cl.ucn.hpc.hpcearch.HPCearch;

public class Main {
	public static void main(final String[] args) throws IOException, InterruptedException{
		String filepath = System.getProperty("user.dir") + File.separatorChar + "downloads";
		String linkInicial = "http://www.ucn.cl";

		comenzarWebCrawler(filepath, linkInicial);
		
		File f = new File(filepath + File.separatorChar +"0PagsRegist.txt");
		System.out.println("Por favor espere un momento mientras se guardan las paginas iniciales.");
		while (!f.exists());
		
		consultasUsuario(filepath);	
	}

	/**
	 * Metodo que inicia el procesamiento de las paginas web
	 * 
	 * @param filepath Ruta donde se almacenaran los resultados de cada pagina
	 * @param linkInicial Pagina con la que se dara comienzo a la aplicacion
	 */
	public static void comenzarWebCrawler(String filepath, String linkInicial){
		HPCearch hpc = new HPCearch(filepath, linkInicial);
		hpc.start();
	}
	
	/**
	 * Metodo que se encarga de atender las consultas del usuario por medio de un menu y entregarle los resultados solicitados.
	 * 
	 * @param filepath Ruta donde se encuentran los archivos que debe consultar
	 * @throws IOException Si hay problemas al leer las lineas
	 * @throws InterruptedException Si hay problemas esperando al procesador de palabras 
	 */
	public static void consultasUsuario(String filepath) throws IOException, InterruptedException{
		System.out.println(Main.printMenu());
		
		final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line = br.readLine();
		
		LinkedBlockingQueue<String> resultado = new LinkedBlockingQueue<String>();
		WordProcessing procesador = new WordProcessing(filepath, resultado);
		
		int opcion = opcionSeleccionada(line);
			
		while(opcion!=4) {
			switch(opcion){
				case 1:
					ejecutarPeticionUsuario(procesador,resultado,1);
					break;
				case 2:
					System.out.println("Ingrese el link de la pagina que desea procesar (incluyendo protocolo http): ");
					BufferedReader breader = new BufferedReader(new InputStreamReader(System.in));
							
					String pagina = breader.readLine();					
					procesador.setURL(pagina);				

					ejecutarPeticionUsuario(procesador,resultado,2);
					break;
				case 3:
					System.out.println("Esta operacion podria tomar algunos minutos, por favor espere");
					ejecutarPeticionUsuario(procesador,resultado,3);
					break;
				default:
					System.out.println("Por favor ingrese un entero entre 1 y 4");
					break;
			}			
			
			System.out.println(Main.printMenu());
			line = br.readLine();
			opcion = opcionSeleccionada(line);
		}
		
		System.out.println("Bye :)");
		System.exit(1); 
	}
	
	/**
	 * Metodo que imprime el menu con sus opciones.
	 * 
	 */
	private static String printMenu() {
		StringBuilder sb = new StringBuilder();

		sb.append("========= MENU ===========").append("\n");
		sb.append("(1) Contar todas las palabras encontradas ").append("\n");
		sb.append("(2) Contar palabras repetidas presentes en una pagina pagina").append("\n");
		sb.append("(3) Contar palabras repetidas de todas las paginas descargadas ").append("\n");
		sb.append("(4) Salir ").append("\n");
		sb.append("==========================").append("\n");

		return sb.toString();
	}
	
	/**
	 * Metodo que imprime el resultado de los calculos.
	 * 
	 * @param resultado Vector con los resultados finales.
	 */	
	private static void printResult(LinkedBlockingQueue<String> resultado) {
		System.out.println("Resultado final:");
	
		for (String stringResultado : resultado) {
			System.out.println(stringResultado);
		}
	}
	
	/**
	 * Metodo que detiene el hilo main el tiempo suficiente para que se realicen los calculos necesarios
	 * en el procesador de palabras.
	 * 
	 * @param procesador Instancia de procesador que indica cuando se encuentra listo.
	 * @throws InterruptedException Si el hilo es interrumpido durante el tiempo que se encuentra dormido.
	 */
	private static void menuWait(WordProcessing procesador) throws InterruptedException {
		Thread.currentThread();
		Thread.sleep(500);
		while(!procesador.isReady()){
			Thread.currentThread();
			Thread.sleep(500);
		}
	}
	
	/**
	 * Metodo que valida que el ingreso sea un entero positivo.
	 * Entrega -1 en caso de no coincidir con el formato solicitado.
	 * 
	 * @param entrada Cadena a revisar
	 * @return Numero convertido
	 */
	private static int opcionSeleccionada(String entrada){
		int num;
		try{
			num = Integer.parseInt(entrada);
			return num;
		}catch(Exception e){
			return -1;
		}						
	}
	
	/**
	 * Procedimiento que realiza la peticion del usuario llamando al metodo correspondiente
	 * 
	 * @param procesador Encargado de realizar la accion solicitada
	 * @param resultado Lista donde se almacenan los resultados
	 * @param opcion Numero de la accion que el usuario quiere ejecutar
	 * @throws InterruptedException Si hay problemas al esperar por el procesador de palabras
	 */
	private static void ejecutarPeticionUsuario(WordProcessing procesador, LinkedBlockingQueue<String> resultado, int opcion) throws InterruptedException{
		procesador.setOpcion(opcion);				
		new Thread(procesador).start();
		
		menuWait(procesador);
		
		printResult(resultado);				
		resultado.clear();
	}
}
